#include "qr.h"
#include "barcode.h"

#include <string>
#include <list>
#include <mutex>
#include <memory>

#include <string.h>

using namespace std;

namespace qr
{

    void test(void)
    {
        return;
    }

#define data_size 64*1024

    char g_decode_data[data_size];
    std::list<std::string> g_list;
    std::mutex mutex;

    int init(void)
    {
        std::string path = "/opt/aio/bin/barcode.cfg";

        int err = BarcodeInitEx(path.c_str());
        if (err != ERR_SCANNER_NO_ERROR) {
            return err;
        }

        return 0;
    }

    int getStatus(void)
    {
        int err = BarcodeStatus();
        if (err != ERR_SCANNER_NO_ERROR) {
            return 2;
        }

        return g_list.empty() ? 0 : 1;
    }

    char* getInfo(void)
    {
        std::lock_guard<std::mutex> lock(mutex);
        memset(g_decode_data, 0, sizeof(g_decode_data));

        int err = BarcodeGetHardwareInfo(g_decode_data);
        if (err != ERR_SCANNER_NO_ERROR) {
            std::string str = std::to_string(err);
            strncpy(g_decode_data, (char*)str.c_str(), str.length());
            return g_decode_data;
        }

        std::string data = g_decode_data;

        std::string info;
        info.append("{\n");
        info.append("\"type\":\"1010\",\n");
        info.append("\"name\":\"QRCode\",\n");
        size_t off = data.find('|', 0);
        info.append("\"manufacturers\"").append(":").append("\"").append(data.substr(0, off)).append("\"").append(",\n");
        info.append("\"model\"").append(":").append("\"").append(data.substr(off + 1, data.find('|', off))).append("\"").append(",\n");
        info.append("\"sdk\":\"1.0.0\",\n");
        info.append("\"description\":\"\"\n");
        info.append("}\n");

        //printf("info is : \n%s\n", info.c_str());

        memset(g_decode_data, 0, sizeof(g_decode_data));
        strncpy(g_decode_data, info.data(), info.length());

        return g_decode_data;
    }

    int doQr(char* data, int size)
    {
        int len = sizeof(g_decode_data);
        if (size < len) {
            return -1;
        }

        std::lock_guard<std::mutex> lock(mutex);
        memset(g_decode_data, 0, sizeof(g_decode_data));

        g_list.push_back("doing");


        int err = BarcodeRead(g_decode_data, &len, 10000);
        if (err != ERR_SCANNER_NO_ERROR) {
            g_list.pop_back();
            return err;
        }

        strncpy(data, g_decode_data, strlen(g_decode_data));

        g_list.pop_back();
        return 0;
    }

    int close(void)
    {
        if (!g_list.empty()) {
            int n_temp = 0;
            int len = sizeof(g_decode_data);
            int err = BarcodeReadCancelAble(g_decode_data, &len, 10000, &n_temp);
            if (err != ERR_SCANNER_NO_ERROR) {
                return -1;
            }
            g_list.clear();
        }

        memset(g_decode_data, 0, sizeof(g_decode_data));

        return 0;
    }

} // namespace qr
